/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package pl.elka.gis.main;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import pl.elka.gis.main.helper.EdgesHelper;
import pl.elka.gis.main.nodesproviders.INodesProvider;
import pl.elka.gis.main.nodesproviders.XMLFileNodesProvider;
import pl.elka.gis.main.node.Node;
import pl.elka.gis.main.node.Edge;
import pl.elka.gis.main.solvers.*;
import pl.elka.gis.main.solvers.ISolver;

/**
 *
 * @author looser
 */
public class AppMediator {    
    private static AppMediator instance = new AppMediator();
    private AppMediator() {
        nodesProvider = new XMLFileNodesProvider("src/resources/nodes.xml");
        solver = new MswSolver();
    }

    public static AppMediator getInstance() {
        return instance;
    }

    private INodesProvider nodesProvider;
    private ISolver solver;

    private Set<Node> nodes = null;
    private Map<String,Set<String>> edgesMap = null;
    private Map<String,Node> nodesMap = null;

    public Map<String,Node> getNodesMap(){
        if(nodesMap == null)
            initNodes();
        return nodesMap;
    }
    public void initNodes(){
        nodes = nodesProvider.provideNodes();
        edgesMap = generateNodesMap(nodes);
        nodesMap = new HashMap<String, Node>();
        for(Node n:nodes){
            nodesMap.put(n.getName(), n);
        }
        
    }
    public Set<Node> getAllNodes(){
        if(nodes == null)
            initNodes();
        return nodes;
    }

    public PaintingHints countPaintingHints(){
        Integer minX = Integer.MAX_VALUE;
        Integer maxX = Integer.MIN_VALUE;

        Integer minY = Integer.MAX_VALUE;
        Integer maxY = Integer.MIN_VALUE;

        for(Node node:getAllNodes()){
            Integer x = node.getX();
            if(x>maxX)
                maxX = x;
            if(x<minX)
                minX = x;

            Integer y = node.getY();
            if(y>maxY)
                maxY = y;
            if(y<minY)
                minY = y;
        }

        PaintingHints hints = new PaintingHints();
        hints.setxRange(maxX - minX);
        hints.setyRange(maxY - minY);
        hints.setMinX(minX);
        hints.setMinY(minY);
        return hints;
    }
    public Set<Edge> getAllEdges(){
        if(edgesMap == null)
            initNodes();
        return EdgesHelper.getAllEdges(edgesMap);
    }
    private Integer sumaSmigania = null;

    public Integer getSumaSmigania() {
        return sumaSmigania;
    }

    public Set<Edge> solve(){
        FileWriter fstream = null;
        Set<Edge> retSet = null;
        try {
            if (edgesMap == null) {
                initNodes();
            }
            retSet = solver.solve(new HashMap<String, Set<String>>(edgesMap));
            int sum = 0;
            fstream = new FileWriter("out.csv");
            BufferedWriter out = new BufferedWriter(fstream);                        
            for (Edge e : retSet) {
                sum += e.getColor();
                out.write(MessageFormat.format("{0},{1},{2}", e.getFrom(),e.getTo(),e.getColor()));
                out.newLine();
            }
            out.close();
            fstream.close();
            sumaSmigania = sum;
            return retSet;
        } catch (IOException ex) {
            ex.printStackTrace();
            return retSet;
        } 
    }

    private Map<String, Set<String>> generateNodesMap(Set<Node> nodesIn) {
        Map<String, Set<String>> retMap = new HashMap<String, Set<String>>();
        for(Node node:nodesIn){
            Set<String> available = new HashSet<String>();
            retMap.put(node.getName(), available);
            for(Node trgNode:node.getAvailableNodes()){
                available.add(trgNode.getName());
            }
        }
        return retMap;
    }
}